package com.ctg.itrdc.imageconsole.control.image;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.ctg.itrdc.imageconsole.common.bean.CommonResult;
import com.ctg.itrdc.imageconsole.common.bean.ReturnCodeDefine;
import com.ctg.itrdc.imageconsole.common.constants.Path;
import com.ctg.itrdc.imageconsole.common.util.DirUtils;
import com.ctg.itrdc.imageconsole.data.dto.DockerMicroImageDTO;
import com.ctg.itrdc.imageconsole.data.entity.DockerMicroImage;
import com.ctg.itrdc.imageconsole.service.IImageBuildService;
import com.ctg.itrdc.pasp.security.utils.WebUtils;
import com.ctg.itrdc.paspsdk.common.entity.PageInfo;

/**
 * 
 * @description: 镜像构建 请求
 * @version: v1.0.0
 * @author: Piao.Wu
 * 
 *          Modification History: Date Author Version Description
 *          -----------------------------------------------------------------
 *          2016年10月24日 下午8:01:47 Piao.Wu v1.0.0 create
 *
 */
@Controller
@RequestMapping("/build")
public class ImageBuildController {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	@Resource
	private IImageBuildService imageBuildService;

	@RequestMapping(value = "/queryBuildList", method = RequestMethod.GET)
	@ResponseBody
	public CommonResult queryBuildList(@RequestParam(value = "imageName", required = false) String imageName,
			@RequestParam(value = "tag", required = false) String tag,
			@RequestParam(value = "status", required = false) String status, @RequestParam("pageNum") int pageNum,
			@RequestParam("pageSize") int pageSize) {
		DockerMicroImage dockerMicroImage = new DockerMicroImage();
		dockerMicroImage.setImageName(imageName);
		dockerMicroImage.setTag(tag);
		dockerMicroImage.setBuildImageStatus(status);
		dockerMicroImage.setCreateUserId(WebUtils.getCtgUser().getSysUserId());
		try {
			PageInfo<DockerMicroImage> pageInfo = imageBuildService.queryBuildList(dockerMicroImage, pageNum,
					pageSize);
			if (pageInfo.getList().size() > 0) {
				return new CommonResult(ReturnCodeDefine.Code.C1000, ReturnCodeDefine.Msg.M1000, pageInfo);
			}
			PageInfo<DockerMicroImage> pageInfoForNull = new PageInfo<>();
			pageInfoForNull.setList(new ArrayList<DockerMicroImage>());

			return new CommonResult(ReturnCodeDefine.Code.C1000, ReturnCodeDefine.Msg.M1000, pageInfoForNull);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return new CommonResult(ReturnCodeDefine.Code.C1200, e.getMessage());
		}
	}

	@RequestMapping(value = "/queryBuildInfo", method = RequestMethod.GET)
	@ResponseBody
	public CommonResult queryBuildInfo(Long dockerMicroImageId) {
		try {
			DockerMicroImage dockerMicroImage = new DockerMicroImage();
			dockerMicroImage.setId(dockerMicroImageId);
			PageInfo<DockerMicroImage> pageInfo = imageBuildService.queryBuildList(dockerMicroImage, 1, 1);
			return new CommonResult(ReturnCodeDefine.Code.C1000, ReturnCodeDefine.Msg.M1000, pageInfo.getList().get(0));
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return new CommonResult(ReturnCodeDefine.Code.C1200, e.getMessage());
		}
	}

	@RequestMapping(value = "buildImage", method = RequestMethod.POST)
	@ResponseBody
	public CommonResult buildImage(@RequestBody DockerMicroImageDTO dockerMicroImageDTO) {
		try {
			dockerMicroImageDTO.setSysUserCode(WebUtils.getCtgUser().getSysUserCode());
			boolean isVersionExist = imageBuildService.isVersionExist(dockerMicroImageDTO.getImageName(), dockerMicroImageDTO.getTag());
			if (isVersionExist) {
				return new CommonResult(ReturnCodeDefine.Code.C1200, "您构建的镜像版本已经存在!");
			}
			boolean isSuccess = imageBuildService.executorImageBuild(dockerMicroImageDTO);
			if (isSuccess) {
				return new CommonResult(ReturnCodeDefine.Code.C1000, ReturnCodeDefine.Msg.M1000);
			} else {
				return new CommonResult(ReturnCodeDefine.Code.C1200, "构建出错!");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return new CommonResult(ReturnCodeDefine.Code.C1200, e.getMessage());
		}
	}

	/**
	 * 
	 * @Description: 查询构建日志
	 * @author Piao.Wu 2016年11月2日 上午9:54:49
	 * @param dockerMicroImageId
	 *            镜像构建记录id
	 * @param lastTimeFileSize
	 *            上次文件大小
	 * @return CommonResult
	 *
	 */
	@RequestMapping(value = "/queryBuildLog", method = RequestMethod.GET)
	@ResponseBody
	public CommonResult queryBuildLog(Long dockerMicroImageId, Long lastTimeFileSize) {
		try {
			Map<String, Object> buildLog = imageBuildService.queryBuildLog(dockerMicroImageId, lastTimeFileSize);
			if (buildLog == null) {
				return new CommonResult(ReturnCodeDefine.Code.C1102, ReturnCodeDefine.Msg.M1102);
			}
			return new CommonResult(ReturnCodeDefine.Code.C1000, ReturnCodeDefine.Msg.M1000, buildLog);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return new CommonResult(ReturnCodeDefine.Code.C1200, e.getMessage());
		}

	}
	
	
	/**
	 * 删除构建记录（不过前端界面做了限制，只允许删除构建失败的记录）
	 * @param dockerMicroImageDTO
	 * @return
	 */
	@RequestMapping(value = "/delete", method = RequestMethod.POST)
	@ResponseBody
	public CommonResult delete(@RequestBody DockerMicroImageDTO dockerMicroImageDTO) {
		try {
			imageBuildService.deleteBuildRecord(dockerMicroImageDTO);
			return new CommonResult(ReturnCodeDefine.Code.C1000, ReturnCodeDefine.Msg.M1000);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return new CommonResult(ReturnCodeDefine.Code.C1200, e.getMessage());
		}
	}
	

	/**
	 * 上传文件分片，合并分片
	 * 
	 * @param multipartFile
	 * @param param
	 * @return
	 * @return CommonResult
	 * @author wupiao
	 * @since 2017年3月6日
	 */
	@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
	@ResponseBody
	public CommonResult uploadFile(@RequestParam(value = "data", required = false) MultipartFile multipartFile,
			@RequestParam Map<String, Object> param) {
		FileInputStream inputStream = null;
		FileOutputStream outputStream = null;
		try {
			String fileName = (String) param.get("fileName");
			String timestampDirectory = (String) param.get("timestampDirectory");
			int total = Integer.parseInt((String) param.get("total"));
			int index = Integer.parseInt((String) param.get("index"));

			String preffixFileName = fileName.substring(0, fileName.lastIndexOf("."));
			// 保存文件的目录
			String fileDirectory = Path.BUILD_FILE_PATH + WebUtils.getCtgUser().getSysUserCode() + "/"
					+ timestampDirectory + "/";
			// 保存文件下所有分片的目录
			String chunkDirectory = fileDirectory + preffixFileName + "/";
			fileDirectory = URLDecoder.decode(fileDirectory, "UTF-8");
			chunkDirectory = URLDecoder.decode(chunkDirectory, "UTF-8");

			File chunkFilePath = new File(chunkDirectory);
			if (!chunkFilePath.getParentFile().getParentFile().exists()) {
				chunkFilePath.getParentFile().getParentFile().mkdir();
			}
			if (!chunkFilePath.getParentFile().exists()) {
				chunkFilePath.getParentFile().mkdir();
			}
			if (!chunkFilePath.exists()) {
				chunkFilePath.mkdir();
			}
			File chunkFile = new File(chunkDirectory, preffixFileName + "_" + index);
			multipartFile.transferTo(chunkFile);

			File[] fileArray = chunkFilePath.listFiles();
			if ((index + 1) == total && fileArray != null && fileArray.length == total) {
				File oldFile = new File(fileDirectory, fileName);
				if (oldFile.exists()) {
					// 如果最终合并成的文件已经存在，则先删除它
					oldFile.delete();
				}
				// 分片全部上传完毕,合并成最终的文件，放到指定目录下
				File newFile = new File(fileDirectory, fileName);
				outputStream = new FileOutputStream(newFile, true);
				byte[] byt = new byte[10 * 1024 * 1024];
				int len;
				for (int i = 0; i < total; i++) {
					inputStream = new FileInputStream(new File(chunkDirectory, preffixFileName + "_" + i));
					while ((len = inputStream.read(byt)) != -1) {
						outputStream.write(byt, 0, len);
					}
					inputStream.close();
				}
				// 清空存放分片文件的整个文件夹
				DirUtils.deleteDir(new File(chunkDirectory));

				logger.info("分片合并完成，文件{}上传成功", fileName);
			}
			return new CommonResult(ReturnCodeDefine.Code.C1000, ReturnCodeDefine.Msg.M1000);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return new CommonResult(ReturnCodeDefine.Code.C1200, e.getMessage());
		} finally {
			try {
				if (inputStream != null) {
					inputStream.close();
				}
				if (outputStream != null) {
					outputStream.close();
				}
			} catch (IOException e) {
				logger.error(e.getMessage(), e);
			}
		}
	}

}
